<!DOCTYPE html>
<html>
<head>
<title>Electromagnetic Field Diagram</title>
<style>
  body {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    margin: 0;
    background-color: #f0f0f0;
  }
  canvas {
    border: 1px solid #ccc;
    background-color: white;
  }
</style>
</head>
<body>
<canvas id="physicsCanvas" width="500" height="550"></canvas>
<script>
  const canvas = document.getElementById('physicsCanvas');
  const ctx = canvas.getContext('2d');
  
  // Style settings
  ctx.strokeStyle = 'black';
  ctx.fillStyle = 'black';
  ctx.lineWidth = 1.5;
  ctx.font = 'italic 22px "Times New Roman"';
  ctx.textAlign = 'center';
  ctx.textBaseline = 'middle';

  // Helper function to draw an arrow
  function drawArrow(fromx, fromy, tox, toy) {
    const headlen = 10;
    const dx = tox - fromx;
    const dy = toy - fromy;
    const angle = Math.atan2(dy, dx);
    ctx.beginPath();
    ctx.moveTo(fromx, fromy);
    ctx.lineTo(tox, toy);
    ctx.lineTo(tox - headlen * Math.cos(angle - Math.PI / 6), toy - headlen * Math.sin(angle - Math.PI / 6));
    ctx.moveTo(tox, toy);
    ctx.lineTo(tox - headlen * Math.cos(angle + Math.PI / 6), toy - headlen * Math.sin(angle + Math.PI / 6));
    ctx.stroke();
  }
  
  // Helper to draw angle arcs
  function drawAngleArc(x, y, radius, startAngle, endAngle, text, textOffset = 1.4) {
      ctx.save();
      ctx.lineWidth = 1;
      ctx.beginPath();
      ctx.arc(x, y, radius, startAngle, endAngle);
      ctx.stroke();
      if (text) {
          const midAngle = (startAngle + endAngle) / 2;
          const textX = x + radius * textOffset * Math.cos(midAngle);
          const textY = y + radius * textOffset * Math.sin(midAngle);
          ctx.fillText(text, textX, textY);
      }
      ctx.restore();
  }
  
  // Parameters
  const ox = 200;
  const oy = 350;
  const R = 150;

  // Rotation axis O1 O'
  ctx.beginPath();
  ctx.setLineDash([5, 3]);
  ctx.moveTo(ox, oy - R - 50);
  ctx.lineTo(ox, oy);
  ctx.stroke();
  ctx.setLineDash([]);
  ctx.fillText("O₁", ox, oy - R - 70);
  ctx.fillText("O'", ox - 20, oy + 5);

  // Arc ab
  ctx.beginPath();
  ctx.arc(ox, oy, R, -Math.PI / 2, 0);
  ctx.stroke();
  const ax = ox;
  const ay = oy - R;
  const bx = ox + R;
  const by = oy;
  ctx.fillText("a", ax - 20, ay);
  ctx.fillText("b", bx + 20, by);
  
  // Dashed lines for quadrant frame
  ctx.beginPath();
  ctx.setLineDash([5, 3]);
  ctx.moveTo(ax, ay); // vertical from a
  ctx.lineTo(ox, oy);
  ctx.moveTo(bx, by); // horizontal from b
  ctx.lineTo(ox, oy);
  ctx.stroke();
  ctx.setLineDash([]);
  
  // Magnetic field B
  drawArrow(ox + 80, 80, ox + 200, 80);
  ctx.font = 'bold italic 24px "Times New Roman"';
  ctx.fillText("B", ox + 225, 80);
  ctx.font = 'italic 22px "Times New Roman"';
  
  // Angular velocity ω
  const omega_cy = 130;
  const omega_r = 30;
  const omega_start_angle = Math.PI * 0.9;
  const omega_end_angle = Math.PI * 0.1;
  ctx.save();
  ctx.lineWidth = 1.5;
  ctx.beginPath();
  ctx.arc(ox, omega_cy, omega_r, omega_start_angle, omega_end_angle, true);
  ctx.stroke();
  // Arrow head for ω
  const arrow_tip_x = ox + omega_r * Math.cos(omega_end_angle);
  const arrow_tip_y = omega_cy + omega_r * Math.sin(omega_end_angle);
  const tangent_angle = omega_end_angle + Math.PI/2;
  const headlen = 8;
  ctx.moveTo(arrow_tip_x, arrow_tip_y);
  ctx.lineTo(arrow_tip_x - headlen * Math.cos(tangent_angle - Math.PI / 6), arrow_tip_y - headlen * Math.sin(tangent_angle - Math.PI / 6));
  ctx.moveTo(arrow_tip_x, arrow_tip_y);
  ctx.lineTo(arrow_tip_x - headlen * Math.cos(tangent_angle + Math.PI / 6), arrow_tip_y - headlen * Math.sin(tangent_angle + Math.PI / 6));
  ctx.stroke();
  ctx.restore();
  ctx.fillText("ω", ox + 55, omega_cy - 5);

  // Infinitesimal element dl
  const alpha = 45 * Math.PI / 180;
  const d_alpha = 8 * Math.PI / 180;
  
  const Px = ox + R * Math.sin(alpha);
  const Py = oy - R * Math.cos(alpha);
  
  const P2x = ox + R * Math.sin(alpha + d_alpha);
  const P2y = oy - R * Math.cos(alpha + d_alpha);
  
  // Radial lines from O'
  ctx.beginPath();
  ctx.moveTo(ox, oy);
  ctx.lineTo(Px, Py);
  ctx.moveTo(ox, oy);
  ctx.lineTo(P2x, P2y);
  ctx.stroke();

  // Label dl on the arc
  const dl_mid_angle = alpha + d_alpha / 2;
  ctx.fillText("dl", ox + R * 1.08 * Math.sin(dl_mid_angle), oy - R * 1.08 * Math.cos(dl_mid_angle));
  
  // Dashed line for radius r and its label
  ctx.beginPath();
  ctx.setLineDash([5, 3]);
  ctx.moveTo(Px, Py);
  ctx.lineTo(ox, Py);
  ctx.stroke();
  ctx.setLineDash([]);
  ctx.fillText("r", ox + (Px - ox) / 2, Py - 15);
  
  // Vertical line from P down
  ctx.beginPath();
  ctx.moveTo(Px, Py);
  ctx.lineTo(Px, oy);
  ctx.stroke();
  
  // Angle α and dα
  drawAngleArc(ox, oy, 40, -Math.PI / 2, -Math.PI/2 + alpha, "α");
  drawAngleArc(ox, oy, 60, -Math.PI / 2 + alpha, -Math.PI/2 + alpha + d_alpha, "dα", 1.05);

  // Angle θ
  // Angle between radius O'P and vertical line from P.
  const angle_theta_start = Math.PI/2;
  const angle_theta_end = Math.atan2(oy-Py, Px-ox);
  drawAngleArc(Px, Py, 30, angle_theta_start, angle_theta_end, "θ");
  
  // Vector v x B
  ctx.save();
  ctx.lineWidth = 2;
  drawArrow(Px, Py, Px, Py + 80);
  ctx.restore();
  ctx.font = 'bold italic 22px "Times New Roman"';
  ctx.fillText("v × B", Px + 45, Py + 40);
  ctx.font = 'italic 22px "Times New Roman"';

  // Label "题 3 图"
  ctx.font = '24px "SimSun"';
  ctx.fillStyle = 'black';
  ctx.fillText("题 3 图", canvas.width / 2, canvas.height - 30);

</script>
</body>
</html>